REBAR = @ESCRIPT@ @rebar@
INSTALL = @INSTALL@
SED = @SED@
ERL = @ERL@

prefix = @prefix@
exec_prefix = @exec_prefix@

DESTDIR =

# /etc/ejabberd/
ETCDIR = $(DESTDIR)@sysconfdir@/ejabberd

# /bin/
BINDIR = $(DESTDIR)@bindir@

# /sbin/
SBINDIR = $(DESTDIR)@sbindir@

# /lib/
LIBDIR =  $(DESTDIR)@libdir@

# /lib/ejabberd/
EJABBERDDIR = $(DESTDIR)@libdir@/ejabberd

# /share/doc/ejabberd
PACKAGE_TARNAME = @PACKAGE_TARNAME@
datarootdir = @datarootdir@
DOCDIR = $(DESTDIR)@docdir@

# /share/doc/man/man5
MANDIR = $(DESTDIR)@mandir@/man5

# /usr/lib/ejabberd/ebin/
BEAMDIR = $(EJABBERDDIR)/ebin

# /usr/lib/ejabberd/include/
INCLUDEDIR = $(EJABBERDDIR)/include

# /usr/lib/ejabberd/priv/
PRIVDIR = $(EJABBERDDIR)/priv

# /usr/lib/ejabberd/priv/bin
PBINDIR = $(PRIVDIR)/bin

# /usr/lib/ejabberd/priv/lib
SODIR = $(PRIVDIR)/lib

# /usr/lib/ejabberd/priv/msgs
MSGSDIR = $(PRIVDIR)/msgs

# /usr/lib/ejabberd/priv/css
CSSDIR = $(PRIVDIR)/css

# /usr/lib/ejabberd/priv/img
IMGDIR = $(PRIVDIR)/img

# /usr/lib/ejabberd/priv/js
JSDIR = $(PRIVDIR)/js

# /usr/lib/ejabberd/priv/sql
SQLDIR = $(PRIVDIR)/sql

# /usr/lib/ejabberd/priv/lua
LUADIR = $(PRIVDIR)/lua

# /var/lib/ejabberd/
SPOOLDIR = $(DESTDIR)@localstatedir@/lib/ejabberd

# /var/lock/ejabberdctl
CTLLOCKDIR = $(DESTDIR)@localstatedir@/lock/ejabberdctl

# /var/lib/ejabberd/.erlang.cookie
COOKIEFILE = $(SPOOLDIR)/.erlang.cookie

# /var/log/ejabberd/
LOGDIR = $(DESTDIR)@localstatedir@/log/ejabberd

INSTALLUSER=@INSTALLUSER@
# if no user was enabled, don't set privileges or ownership
ifeq ($(INSTALLUSER),)
  O_USER=
  G_USER=
  CHOWN_COMMAND=echo
  CHOWN_OUTPUT=/dev/null
  INIT_USER=root
else
  O_USER=-o $(INSTALLUSER)
  G_USER=-g $(INSTALLUSER)
  CHOWN_COMMAND=chown
  CHOWN_OUTPUT=&1
  INIT_USER=$(INSTALLUSER)
endif
# if no group was enabled, don't set privileges or ownership
INSTALLGROUP=@INSTALLGROUP@
ifneq ($(INSTALLGROUP),)
  G_USER=-g $(INSTALLGROUP)
endif

IS_REBAR3:=$(shell expr `$(REBAR) --version | awk -F '[ .]' '/rebar / {print $$2}'` '>=' 3)

ifeq "$(IS_REBAR3)" "1"
  SKIPDEPS=
  LISTDEPS=tree
  UPDATEDEPS=upgrade
  DEPSPATTERN="s/ (.*//; /^ / s/.* \([a-z0-9_]*\).*/\1/p;"
  DEPSBASE=_build
  DEPSDIR=$(DEPSBASE)/default/lib
  EBINDIR=$(DEPSDIR)/ejabberd/ebin
else
  SKIPDEPS=skip_deps=true
  LISTDEPS=-q list-deps
  UPDATEDEPS=update-deps
  DEPSPATTERN="/ TAG / s/ .*// p; / REV / s/ .*// p; / BRANCH / s/ .*// p;"
  DEPSBASE=deps
  DEPSDIR=$(DEPSBASE)
  EBINDIR=ebin
endif

all: deps src

deps: $(DEPSDIR)/.got

$(DEPSDIR)/.got:
	rm -rf $(DEPSDIR)/.got
	rm -rf $(DEPSDIR)/.built
	mkdir -p $(DEPSDIR)
	$(REBAR) get-deps && :> $(DEPSDIR)/.got

$(DEPSDIR)/.built: $(DEPSDIR)/.got
	$(REBAR) configure-deps
	$(REBAR) compile && :> $(DEPSDIR)/.built

src: $(DEPSDIR)/.built
	$(REBAR) $(SKIPDEPS) compile

update:
	rm -rf $(DEPSDIR)/.got
	rm -rf $(DEPSDIR)/.built
	$(REBAR) $(UPDATEDEPS) && :> $(DEPSDIR)/.got

xref: all
	$(REBAR) $(SKIPDEPS) xref

hooks: all
	tools/hook_deps.sh $(EBINDIR)

options: all
	tools/opt_types.sh ejabberd_option $(EBINDIR)

translations:
	tools/prepare-tr.sh $(DEPSDIR)

edoc:
	$(ERL) -noinput +B -eval \
        'case edoc:application(ejabberd, ".", []) of ok -> halt(0); error -> halt(1) end.'

JOIN_PATHS=$(if $(wordlist 2,1000,$(1)),$(firstword $(1))/$(call JOIN_PATHS,$(wordlist 2,1000,$(1))),$(1))

VERSIONED_DEP=$(if $(DEP_$(1)_VERSION),$(DEP_$(1)_VERSION),$(1))

DEPIX:=$(words $(subst /, ,$(DEPSDIR)))
LIBIX:=$(shell expr "$(DEPIX)" + 2)

ELIXIR_TO_DEST=$(LIBDIR) $(call VERSIONED_DEP,$(word 2,$(1))) $(wordlist 5,1000,$(1))
DEPS_TO_DEST=$(LIBDIR) $(call VERSIONED_DEP,$(word 2,$(1))) $(wordlist 3,1000,$(1))
MAIN_TO_DEST=$(LIBDIR) $(call VERSIONED_DEP,ejabberd) $(1)
TO_DEST_SINGLE=$(if $(subst X$(DEPSBASE)X,,X$(word 1,$(1))X),$(call MAIN_TO_DEST,$(1)),$(if $(subst XlibX,,X$(word $(LIBIX),$(1))X),$(call DEPS_TO_DEST,$(wordlist $(DEPIX),1000,$(1))),$(call ELIXIR_TO_DEST,$(wordlist $(DEPIX),1000,$(1)))))
TO_DEST=$(foreach path,$(1),$(call JOIN_PATHS,$(call TO_DEST_SINGLE,$(subst /, ,$(path)))))

FILTER_DIRS=$(foreach path,$(1),$(if $(wildcard $(path)/*),,$(path)))
FILES_WILDCARD=$(call FILTER_DIRS,$(foreach w,$(1),$(wildcard $(w))))

ifeq ($(MAKECMDGOALS),copy-files-sub)

DEPS:=$(sort $(shell QUIET=1 $(REBAR) $(LISTDEPS) | $(SED) -ne $(DEPSPATTERN) ))

DEPS_FILES=$(call FILES_WILDCARD,$(foreach DEP,$(DEPS),$(DEPSDIR)/$(DEP)/ebin/*.beam $(DEPSDIR)/$(DEP)/ebin/*.app $(DEPSDIR)/$(DEP)/priv/* $(DEPSDIR)/$(DEP)/priv/lib/* $(DEPSDIR)/$(DEP)/priv/bin/* $(DEPSDIR)/$(DEP)/include/*.hrl $(DEPSDIR)/$(DEP)/COPY* $(DEPSDIR)/$(DEP)/LICENSE* $(DEPSDIR)/$(DEP)/lib/*/ebin/*.beam $(DEPSDIR)/$(DEP)/lib/*/ebin/*.app))

BINARIES=$(DEPSDIR)/epam/priv/bin/epam $(DEPSDIR)/eimp/priv/bin/eimp $(DEPSDIR)/fs/priv/mac_listener

DEPS_FILES_FILTERED=$(filter-out $(BINARIES) $(DEPSDIR)/elixir/ebin/elixir.app,$(DEPS_FILES))
DEPS_DIRS=$(sort $(DEPSDIR)/ $(foreach DEP,$(DEPS),$(DEPSDIR)/$(DEP)/) $(dir $(DEPS_FILES)))

MAIN_FILES=$(filter-out %/configure.beam,$(call FILES_WILDCARD,$(EBINDIR)/*.beam $(EBINDIR)/*.app priv/msgs/*.msg priv/css/*.css priv/img/*.png priv/js/*.js priv/lib/* include/*.hrl COPYING))
MAIN_DIRS=$(sort $(dir $(MAIN_FILES)) priv/bin priv/sql priv/lua)

define DEP_VERSION_template
DEP_$(1)_VERSION:=$(shell $(SED) -e '/vsn/!d;s/.*, *"/$(1)-/;s/".*//' $(2) 2>/dev/null)
endef

DELETE_TARGET_SO=$(if $(subst X.soX,,X$(suffix $(1))X),,rm -f $(call TO_DEST,$(1));)

$(foreach DEP,$(DEPS),$(eval $(call DEP_VERSION_template,$(DEP),$(DEPSDIR)/$(DEP)/ebin/$(DEP).app)))
$(eval $(call DEP_VERSION_template,ejabberd,$(EBINDIR)/ejabberd.app))

define COPY_template
$(call TO_DEST,$(1)): $(1) $(call TO_DEST,$(dir $(1))) ; $(call DELETE_TARGET_SO, $(1)) $$(INSTALL) -m 644 $(1) $(call TO_DEST,$(1))
endef

define COPY_BINARY_template
$(call TO_DEST,$(1)): $(1) $(call TO_DEST,$(dir $(1))) ; rm -f $(call TO_DEST,$(1)); $$(INSTALL) -m 755 $$(O_USER) $(1) $(call TO_DEST,$(1))
endef

$(foreach file,$(DEPS_FILES_FILTERED) $(MAIN_FILES),$(eval $(call COPY_template,$(file))))

$(foreach file,$(BINARIES),$(eval $(call COPY_BINARY_template,$(file))))

$(sort $(call TO_DEST,$(MAIN_DIRS) $(DEPS_DIRS))):
	$(INSTALL) -d $@

$(call TO_DEST,priv/sql/lite.sql): sql/lite.sql $(call TO_DEST,priv/sql)
	$(INSTALL) -m 644 $< $@

$(call TO_DEST,priv/sql/lite.new.sql): sql/lite.new.sql $(call TO_DEST,priv/sql)
	$(INSTALL) -m 644 $< $@

$(call TO_DEST,priv/bin/captcha.sh): tools/captcha.sh $(call TO_DEST,priv/bin)
	$(INSTALL) -m 755 $(O_USER) $< $@

$(call TO_DEST,priv/lua/redis_sm.lua): priv/lua/redis_sm.lua $(call TO_DEST,priv/lua)
	$(INSTALL) -m 644 $< $@

copy-files-sub2: $(call TO_DEST,$(DEPS_FILES) $(MAIN_FILES) priv/bin/captcha.sh priv/sql/lite.sql priv/sql/lite.new.sql priv/lua/redis_sm.lua)

.PHONY: $(call TO_DEST,$(DEPS_FILES) $(MAIN_DIRS) $(DEPS_DIRS))

endif

copy-files:
	$(MAKE) copy-files-sub

copy-files-sub: copy-files-sub2

install: copy-files
	#
	# Configuration files
	$(INSTALL) -d -m 750 $(G_USER) $(ETCDIR)
	[ -f $(ETCDIR)/ejabberd.yml ] \
		&& $(INSTALL) -b -m 640 $(G_USER) ejabberd.yml.example $(ETCDIR)/ejabberd.yml-new \
		|| $(INSTALL) -b -m 640 $(G_USER) ejabberd.yml.example $(ETCDIR)/ejabberd.yml
	$(SED) -e "s*{{rootdir}}*@prefix@*g" \
		-e "s*{{installuser}}*@INSTALLUSER@*g" \
		-e "s*{{bindir}}*@bindir@*g" \
		-e "s*{{libdir}}*@libdir@*g" \
		-e "s*{{sysconfdir}}*@sysconfdir@*g" \
		-e "s*{{localstatedir}}*@localstatedir@*g" \
		-e "s*{{docdir}}*@docdir@*g" \
		-e "s*{{erl}}*@ERL@*g" \
		-e "s*{{epmd}}*@EPMD@*g" ejabberdctl.template \
		> ejabberdctl.example
	[ -f $(ETCDIR)/ejabberdctl.cfg ] \
		&& $(INSTALL) -b -m 640 $(G_USER) ejabberdctl.cfg.example $(ETCDIR)/ejabberdctl.cfg-new \
		|| $(INSTALL) -b -m 640 $(G_USER) ejabberdctl.cfg.example $(ETCDIR)/ejabberdctl.cfg
	$(INSTALL) -b -m 644 $(G_USER) inetrc $(ETCDIR)/inetrc
	#
	# Administration script
	[ -d $(SBINDIR) ] || $(INSTALL) -d -m 755 $(SBINDIR)
	$(INSTALL) -m 550 $(G_USER) ejabberdctl.example $(SBINDIR)/ejabberdctl
	# Elixir binaries
	[ -d $(BINDIR) ] || $(INSTALL) -d -m 755 $(BINDIR)
	[ -f $(DEPSDIR)/elixir/bin/iex ] && $(INSTALL) -m 550 $(G_USER) $(DEPSDIR)/elixir/bin/iex $(BINDIR)/iex || true
	[ -f $(DEPSDIR)/elixir/bin/elixir ] && $(INSTALL) -m 550 $(G_USER) $(DEPSDIR)/elixir/bin/elixir $(BINDIR)/elixir || true
	[ -f $(DEPSDIR)/elixir/bin/mix ] && $(INSTALL) -m 550 $(G_USER) $(DEPSDIR)/elixir/bin/mix $(BINDIR)/mix || true
	#
	# Init script
	$(SED) -e "s*@ctlscriptpath@*$(SBINDIR)*g" \
		-e "s*@installuser@*$(INIT_USER)*g" ejabberd.init.template \
		> ejabberd.init
	chmod 755 ejabberd.init
	#
	# Service script
	$(SED) -e "s*@ctlscriptpath@*$(SBINDIR)*g" ejabberd.service.template \
		> ejabberd.service
	chmod 644 ejabberd.service
	#
	# Spool directory
	$(INSTALL) -d -m 750 $(O_USER) $(SPOOLDIR)
	$(CHOWN_COMMAND) -R @INSTALLUSER@ $(SPOOLDIR) >$(CHOWN_OUTPUT)
	chmod -R 750 $(SPOOLDIR)
	[ ! -f $(COOKIEFILE) ] || { $(CHOWN_COMMAND) @INSTALLUSER@ $(COOKIEFILE) >$(CHOWN_OUTPUT) ; chmod 400 $(COOKIEFILE) ; }
	#
	# ejabberdctl lock directory
	$(INSTALL) -d -m 750 $(O_USER) $(CTLLOCKDIR)
	$(CHOWN_COMMAND) -R @INSTALLUSER@ $(CTLLOCKDIR) >$(CHOWN_OUTPUT)
	chmod -R 750 $(CTLLOCKDIR)
	#
	# Log directory
	$(INSTALL) -d -m 750 $(O_USER) $(LOGDIR)
	$(CHOWN_COMMAND) -R @INSTALLUSER@ $(LOGDIR) >$(CHOWN_OUTPUT)
	chmod -R 750 $(LOGDIR)
	#
	# Documentation
	$(INSTALL) -d $(MANDIR)
	$(INSTALL) -d $(DOCDIR)
	[ -f man/ejabberd.yml.5 ] \
		&& $(INSTALL) -m 644 man/ejabberd.yml.5 $(MANDIR) \
		|| echo "Man page not included in sources"
	$(INSTALL) -m 644 COPYING $(DOCDIR)

uninstall: uninstall-binary

uninstall-binary:
	rm -f  $(SBINDIR)/ejabberdctl
	rm -f  $(BINDIR)/iex
	rm -f  $(BINDIR)/elixir
	rm -f  $(BINDIR)/mix
	rm -fr $(DOCDIR)
	rm -f  $(BEAMDIR)/*.beam
	rm -f  $(BEAMDIR)/*.app
	rm -fr $(BEAMDIR)
	rm -f  $(INCLUDEDIR)/*.hrl
	rm -fr $(INCLUDEDIR)
	rm -fr $(PBINDIR)
	rm -f  $(SODIR)/*.so
	rm -fr $(SODIR)
	rm -f  $(MSGSDIR)/*.msg
	rm -fr $(MSGSDIR)
	rm -f  $(CSSDIR)/*.css
	rm -fr $(CSSDIR)
	rm -f  $(IMGDIR)/*.png
	rm -fr $(IMGDIR)
	rm -f  $(JSDIR)/*.js
	rm -fr $(JSDIR)
	rm -f  $(SQLDIR)/*.sql
	rm -fr $(SQLDIR)
	rm -fr $(LUADIR)/*.lua
	rm -fr $(LUADIR)
	rm -fr $(PRIVDIR)
	rm -fr $(EJABBERDDIR)

uninstall-all: uninstall-binary
	rm -rf $(ETCDIR)
	rm -rf $(EJABBERDDIR)
	rm -rf $(SPOOLDIR)
	rm -rf $(CTLLOCKDIR)
	rm -rf $(LOGDIR)

clean:
	rm -rf $(DEPSDIR)/.got
	rm -rf $(DEPSDIR)/.built
	rm -rf test/*.beam
	$(REBAR) clean

clean-rel:
	rm -rf rel/ejabberd

distclean: clean clean-rel
	rm -f config.status
	rm -f config.log
	rm -rf autom4te.cache
	rm -rf $(EBINDIR)
	rm -rf $(DEPSBASE)
	rm -f Makefile
	rm -f vars.config
	rm -f src/ejabberd.app.src
	rm -f ejabberdctl.example ejabberd.init ejabberd.service
	[ ! -f ../ChangeLog ] || rm -f ../ChangeLog

rel: all
	$(REBAR) generate

TAGS:
	etags *.erl

Makefile: Makefile.in

ifeq "$(IS_REBAR3)" "1"
dialyzer:
	$(REBAR) dialyzer
else
deps := $(wildcard $(DEPSDIR)/*/ebin)

dialyzer/erlang.plt:
	@mkdir -p dialyzer
	@dialyzer --build_plt --output_plt dialyzer/erlang.plt \
	-o dialyzer/erlang.log --apps kernel stdlib sasl crypto \
	public_key ssl mnesia inets odbc compiler erts \
	os_mon asn1 syntax_tools; \
	status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi

dialyzer/deps.plt:
	@mkdir -p dialyzer
	@dialyzer --build_plt --output_plt dialyzer/deps.plt \
	-o dialyzer/deps.log $(deps); \
	status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi

dialyzer/ejabberd.plt:
	@mkdir -p dialyzer
	@dialyzer --build_plt --output_plt dialyzer/ejabberd.plt \
	-o dialyzer/ejabberd.log ebin; \
	status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi

erlang_plt: dialyzer/erlang.plt
	@dialyzer --plt dialyzer/erlang.plt --check_plt -o dialyzer/erlang.log; \
	status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi

deps_plt: dialyzer/deps.plt
	@dialyzer --plt dialyzer/deps.plt --check_plt -o dialyzer/deps.log; \
	status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi

ejabberd_plt: dialyzer/ejabberd.plt
	@dialyzer --plt dialyzer/ejabberd.plt --check_plt -o dialyzer/ejabberd.log; \
	status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi

dialyzer: erlang_plt deps_plt ejabberd_plt
	@dialyzer --plts dialyzer/*.plt --no_check_plt \
	--get_warnings -o dialyzer/error.log ebin; \
	status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi
endif

test:
	@echo "************************** NOTICE ***************************************"
	@cat test/README
	@echo "*************************************************************************"
	@cd priv && ln -sf ../sql
	$(REBAR) $(SKIPDEPS) ct

.PHONY: src edoc dialyzer Makefile TAGS clean clean-rel distclean rel \
	install uninstall uninstall-binary uninstall-all translations deps test \
	quicktest erlang_plt deps_plt ejabberd_plt xref hooks options
